<!--
 * @Date: 2022-03-29 11:05:28
 * @LastEditors: sailornpg
 * @LastEditTime: 2022-11-29 14:11:39
 * @FilePath: \vue-admin-ts\src\components\Table\Table.vue
 * @Description: something
-->
<template>
  <div class="table_header">
    <slot name="tableHeader"></slot>
  </div>
  <el-table
    :data="tabledata"
    v-loading="isLoading"
    :element-loading-text="elementLoadingText"
    :element-loading-spinner="elementLoadingSpinner"
    :element-loading-background="elementLoadingBackground"
    :element-loading-svg="elementLoadingSvg"
    :element-loading-svg-view-box="elementLoadingSvgViewBox"
    v-bind="$attrs"
    @row-click="rowClick"
    @selection-change="selectionChangeHandler"
  >
    <el-table-column v-if="isCheck" type="selection" width="55" align="center">
    </el-table-column>
    <el-table-column v-if="showIndex" type="index" label="序号" align="center">
    </el-table-column>
    <template v-for="(item, index) in tableoptions" :key="index">
      <!-- 自定义插槽 -->
      <el-table-column
        :prop="item.prop"
        :label="item.label"
        :align="item.align"
        :width="item.width"
        v-bind="item.itemAttrs"
      >
        <template #default="scope">
          <template v-if="scope.row.rowEdit">
            <el-input size="small" v-model="scope.row[item.prop!]"></el-input>
          </template>
          <template v-else>
            <template v-if="scope.$index + scope.column.id === currentEdit">
              <div style="display: flex; align-items: center">
                <el-input
                  size="small"
                  v-model="scope.row[item.prop!]"
                ></el-input>
                <!-- 或者自定义编辑内容 -->
                <div @click.stop="clickEditCell">
                  <slot
                    name="editArea"
                    :scope="scope"
                    v-if="$slots.editArea"
                  ></slot>
                  <div class="icons" v-else>
                    <component
                      :is="checkIcon"
                      class="check"
                      @click="confirm(scope)"
                    ></component>
                    <component
                      :is="closeIcon"
                      class="close"
                      @click="cancel(scope)"
                    ></component>
                  </div>
                </div>
              </div>
            </template>
            <template v-else>
              <slot v-if="item.slot" :name="item.slot" :scope="scope"></slot>
              <span v-else>{{ scope.row[item.prop!] }}</span>
              <component
                v-if="item.editable"
                :is="editIcon"
                class="edit"
                @click.stop="editHandler(scope)"
              ></component>
            </template>
          </template>
        </template>
      </el-table-column>
    </template>
    <!-- 操作 -->
    <el-table-column
      v-if="operation"
      :prop="operation.prop"
      :label="operation.label"
      :align="operation.align"
    >
      <template #default="scope">
        <slot name="editRow" v-if="scope.row.rowEdit" :scope="scope"></slot>
        <slot name="operation" v-else :scope="scope"></slot>
      </template>
    </el-table-column>
  </el-table>
  <div
    v-if="pagination && !isLoading"
    class="pagination"
    :style="{ justifyContent }"
  >
    <el-pagination
      v-model:currentPage="pageInfo.currentPage"
      v-model:page-size="pageInfo.pageSize"
      :page-sizes="pageSizes"
      layout="total, sizes, prev, pager, next, jumper"
      :total="total"
      @size-change="handleSizeChange"
      @current-change="handleCurrentChange"
    />
  </div>
</template>
<script lang="ts" setup>
import { PropType, computed, ref, onMounted, watch } from "vue";
import { TableOptions } from "./type/type";
import cloneDeep from "lodash/cloneDeep";
const props = defineProps({
  options: {
    type: Array as PropType<TableOptions[]>,
    required: true,
  },
  TableData: {
    type: Array as PropType<any[]>,
    required: true,
  },
  showIndex: {
    type: Boolean,
    default: false,
  },
  isCheck: {
    type: Boolean,
    default: false,
  },
  // 加载文案
  elementLoadingText: {
    type: String,
  },
  // 加载图标名
  elementLoadingSpinner: {
    type: String,
  },
  // 加载背景颜色
  elementLoadingBackground: {
    type: String,
  },
  // 加载图标是svg
  elementLoadingSvg: {
    type: String,
  },
  // 加载团是svg的配置
  elementLoadingSvgViewBox: {
    type: String,
  },
  //编辑按钮
  editIcon: {
    type: String,
    default: "Edit",
  },
  //编辑完毕打勾按钮
  checkIcon: {
    type: String,
    default: "Check",
  },
  //编辑取消按钮
  closeIcon: {
    type: String,
    default: "Close",
  },
  // 编辑行按钮的标识
  editRowIndex: {
    type: String,
    default: "",
  },
  // 是否可以编辑行
  isEditRow: {
    type: Boolean,
    default: false,
  },
  // 是否显示分页
  pagination: {
    type: Boolean,
    default: false,
  },
  // 显示分页的对齐方式
  paginationAlign: {
    type: String as PropType<"left" | "center" | "right">,
    default: "left",
  },
  // // 当前是第几页
  // currentPage: {
  //   type: Number,
  //   default: 1,
  // },
  // // 当前一页多少条数据
  // pageSize: {
  //   type: Number,
  //   default: 10,
  // },
  pageInfo: {
    type: Object,
    default: () => ({ currentPage: 0, pageSize: 10 }),
  },
  // 显示分页数据多少条的选项
  pageSizes: {
    type: Array,
    default: () => [10, 20, 30, 40],
  },
  // 数据总条数
  total: {
    type: Number,
    default: 0,
  },
  isLoading: {
    type: Boolean,
  },
});
//深拷贝表格数据
let tabledata = ref<any[]>(cloneDeep(props.TableData));
//拷贝标识
let cloneEditRowIndex = ref<string>(props.editRowIndex);
const emits = defineEmits([
  "onConfirm",
  "onCancel",
  "update:editRowIndex",
  "sizeChange",
  "currentChange",
  "update:selectArray",
  "update:pageInfo",
]);
//当前编辑的单元格
let currentEdit = ref<string>("");
//过滤没有操作项，仅显示
let tableoptions = computed(() => props.options.filter((item) => !item.action));
//选出具有操作的选项
let operation = computed(() => props.options.find((item) => item.action));
// 表格分页的排列方式
let justifyContent = computed(() => {
  if (props.paginationAlign === "left") return "flex-start";
  else if (props.paginationAlign === "right") return "flex-end";
  else return "center";
});
//选中改变
const selectionChangeHandler = (val: any) => {
  emits("update:selectArray", val);
};
//点击编辑按钮
const editHandler = (scope: any) => {
  currentEdit.value = scope.$index + scope.column.id;
};
//判断点击行
const rowClick = (row: any, column: any) => {
  if (column.label === (operation.value && operation.value.label)) {
    //点中操作
    if (props.isEditRow && cloneEditRowIndex.value === props.editRowIndex) {
      // 编辑行的操作
      row.rowEdit = !row.rowEdit;
      // 重置其他数据的rowEdit
      tabledata.value.map((item) => {
        if (item !== row) item.rowEdit = false;
      });
      // 重置按钮的标识
      if (!row.rowEdit) emits("update:editRowIndex", "");
    }
  }
};
//监听父组件传来的值
watch(
  () => props.TableData,
  (val) => {
    tabledata.value = cloneDeep(val);
    tabledata.value.map((item) => {
      //代表是否可编辑
      item.rowEdit = false;
    });
  },
  { deep: true },
);
watch(
  () => props.editRowIndex,
  (val) => {
    if (val) {
      cloneEditRowIndex.value = val;
    }
  },
);
onMounted(() => {
  tabledata.value.map((item) => {
    //代表是否可编辑
    item.rowEdit = false;
  });
});
const clickEditCell = () => {
  currentEdit.value = "";
};
//关闭回调
const confirm = (scope: any) => {
  currentEdit.value = "";
  emits("onConfirm", scope);
};
const cancel = (scope: any) => {
  currentEdit.value = "";
  emits("onCancel", scope);
};
const handleSizeChange = (pageSize: any) => {
  console.log(pageSize, "pageSize");
  emits("update:pageInfo", { ...props.pageInfo, pageSize });
};
const handleCurrentChange = (currentPage: any) => {
  console.log(currentPage, "currentPage");
  // emits("currentChange", currentPage);
  emits("update:pageInfo", { ...props.pageInfo, currentPage });
};
</script>
<style lang="less" scoped>
.edit {
  width: 1em;
  height: 1em;
  position: relative;
  top: 2px;
  left: 4px;
  cursor: pointer;
  &:hover {
    color: #409eff;
  }
}
.icons {
  display: flex;
  margin-left: 5px;

  svg {
    width: 1.1em;
    height: 1.1em;
  }
  .check {
    color: green;
    margin-left: 5px;
    cursor: pointer;
  }
  .close {
    color: red;
    margin-left: 5px;
    cursor: pointer;
  }
}
.pagination {
  margin-top: 16px;
  display: flex;
}
</style>
